package com.sunfeng.elasticsearch.elastic.compound;

import com.sunfeng.elasticsearch.utils.ClientUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.DisMaxQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.IOException;

/**
 * @Author : 孙峰
 * @Description:
 * @Date : 2022/5/7  14:40
 */
public class MultiMatchQuery {
    public static void main(String[] args) throws IOException {
        // 创建客户端对象
        RestHighLevelClient client = null;
        try {
            client = ClientUtils.getInstance();
            multiMatchQuery(client);
        } finally {
            assert client != null;
            client.close();
        }
    }

    /**
     * 这个查询与disjunction max query的效果相同
     * the score from the best matching field 得分来自于最佳匹配字段
     * plus tie_breaker * _score for all other matching fields
     * 加上tie_breaker * 所有匹配的字段的得分
     *
     * @param client
     * @throws IOException
     */
    private static void multiMatchQuery(RestHighLevelClient client) throws IOException {

        SearchRequest searchRequest = new SearchRequest().indices("blogs");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery("Quick pets", "title", "body");
        multiMatchQuery.type(MultiMatchQueryBuilder.Type.BEST_FIELDS);
        multiMatchQuery.tieBreaker(0.2f);
        multiMatchQuery.minimumShouldMatch("1");
        sourceBuilder.query(multiMatchQuery);

        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = search.getHits();
        System.out.println(hits.getTotalHits());
        for (SearchHit hit : hits) {
            System.out.println(hit.getScore());
            System.out.println(hit.getSourceAsMap());
        }
    }

    /**
     * 通配符查询 查询 title first_name ,last_name
     * <p>
     * 内部的查询方式multi_much取决于type参数，可设置为
     * best_fields:（默认）查找与任何字段匹配的文档，但使用 _score来自最佳字段的文档。
     * most_fields: 查找与任何字段匹配的文档并组合_score来自每个字段的文档。
     * most_fields当查询包含以不同方式分析的相同文本的多个字段时，该类型最有用，，主字段可能包含同义词、词干和没有变音符号的术语。
     * 第二个字段可能包含原始术语，第三个字段可能包含 shingles。通过结合所有三个字段的分数，
     * 我们可以将尽可能多的文档与主字段匹配，但使用第二个和第三个字段将最相似的结果推到列表的顶部。
     * <p>
     * cross_fields: 将字段analyzer视为一个大字段。查找任何 字段中的每个单词。
     * phrase: match_phrase对每个字段 运行查询并使用_score 最佳字段中的
     *
     * @param client
     * @throws IOException
     */

    private static void specifiedWithWildcardsQuery(RestHighLevelClient client) throws IOException {

        SearchRequest searchRequest = new SearchRequest().indices("blogs");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
     /*   MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery("Quick pets", "title", "*_name" );
        //multiMatchQuery2 中 title 重要性 是其他字段的三倍
        MultiMatchQueryBuilder multiMatchQuery2 = QueryBuilders.multiMatchQuery("Quick pets", "title^3", "*_name" );
            sourceBuilder.query(multiMatchQuery);
*/
        //       ======================================      multiMatchQuery+MOST_FIELDS
//        MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery("quick brown fox", "title", "title.original", "title.shingles");
//        multiMatchQuery.type(MultiMatchQueryBuilder.Type.MOST_FIELDS);
//        sourceBuilder.query(multiMatchQuery);
//
//        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//        boolQuery.should(QueryBuilders.matchQuery("title","quick brown fox"));
//        boolQuery.should(QueryBuilders.matchQuery("title.original","quick brown fox"));
//        boolQuery.should(QueryBuilders.matchQuery("title.shingles","quick brown fox"));

        //       ======================================multiMatchQuery+ phrase and phrase_prefix
//         MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery("quick brown f", "subject", "message" );
//         multiMatchQuery.type(MultiMatchQueryBuilder.Type.PHRASE_PREFIX);
//        sourceBuilder.query(multiMatchQuery);
//    // 上下实现功能展示一直
//        DisMaxQueryBuilder disMaxQuery = QueryBuilders.disMaxQuery();
//        disMaxQuery.add(QueryBuilders.matchPhrasePrefixQuery("subject","quick brown f"));
//        disMaxQuery.add(QueryBuilders.matchQuery("message","quick brown f"));
//        sourceBuilder.query(disMaxQuery);

        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = search.getHits();
        System.out.println(hits.getTotalHits());
        for (SearchHit hit : hits) {
            System.out.println(hit.getScore());
            System.out.println(hit.getSourceAsMap());
        }
    }

}
